package com.xiaobawang.xjsyy_idea_plugin.service;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.xiaobawang.xjsyy_idea_plugin.panel.dev_process.struct.*;
import com.xiaobawang.xjsyy_idea_plugin.forest.*;
import com.xiaobawang.xjsyy_idea_plugin.panel.dev_process.struct.DevProcess;
import com.xiaobawang.xjsyy_idea_plugin.util.GsonUtil;
import org.yaml.snakeyaml.Yaml;

import java.io.StringReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * @author synhard
 * @description TODO
 * @date 2024/6/4 17:38
 * @email songxinhang2023@e-chinalife.com
 * @id 18101119
 * @phone 13001321080
 */
public class Service {

    /**
     * @author synhard
     * @id 18101119
     * @description 获取研发流程运行历史
     * @date 2024/5/29 18:46
     */
    public static List<RunningHistory> runningHistory(Long pipelineId, Integer pageNumber, Integer pageSize) {
        // 调用云效获取研发流程运行历史
        String runningHistoryRes = ForestApi.runningHistory(pipelineId, pageNumber, pageSize);
        Type listType = new TypeToken<List<RunningHistory>>() {
        }.getType();
        List<RunningHistory> runningHistoryList = GsonUtil.getGson().fromJson(runningHistoryRes, listType);
        for (RunningHistory runningHistory : runningHistoryList) {
            // 调用云效获取运行详情
            String                              runningDetailRes = ForestApi.runningDetail(runningHistory.getPipelineId(), runningHistory.getPipelineRunId());
            RunningDetail                       runningDetail    = GsonUtil.getGson().fromJson(runningDetailRes, RunningDetail.class);
            List<RunningHistory.StageInfo>      stageInfoList    = new ArrayList<>(5);
            List<RunningHistory.CodeSourceInfo> codeURLList      = new ArrayList<>(5);
            for (RunningDetail.Stage stage : runningDetail.getStages()) {
                RunningHistory.StageInfo stageInfo = new RunningHistory.StageInfo();
                stageInfo.setName(stage.getStageInfo().getName());
                stageInfo.setStatus(stage.getStageInfo().getStatus());
                stageInfoList.add(stageInfo);
            }
            for (RunningDetail.Source source : runningDetail.getSources()) {
                RunningHistory.CodeSourceInfo codeSourceInfo = new RunningHistory.CodeSourceInfo();
                codeSourceInfo.setBranch(source.getData().getBranch());
                codeSourceInfo.setUrl(source.getData().getRepo());
                codeURLList.add(codeSourceInfo);
            }
            runningHistory.setStageInfoList(stageInfoList);
            runningHistory.setCodeURLList(codeURLList);
        }
        return runningHistoryList;
    }

    /**
     * @author synhard
     * @id 18101119
     * @description 获取研发流程
     * @date 2024/5/29 18:47
     */
    public static List<DevProcess> releaseWorks() {
        // 调用云效获取应用的所有研发流程
        String     releaseWorkflowsRes   = ForestApi.releaseWorkflows();
        JsonArray  releaseWorkflowsResJA = GsonUtil.parseStringToJsonArray(releaseWorkflowsRes);
        JsonObject releaseWorkflowsResJO = releaseWorkflowsResJA.get(0).getAsJsonObject();
        // 规范化云效接口研发流程的响应
        ReleaseWorkFlows releaseWorkFlows = GsonUtil.getGson().fromJson(releaseWorkflowsResJO, ReleaseWorkFlows.class);
        // 将云效接口的研发流程响应转化为项目中的结构体
        List<DevProcess> devProcessList = new ArrayList<>(5);
        for (ReleaseWorkFlows.ReleaseStage releaseStage : releaseWorkFlows.getReleaseStages()) {
            DevProcess devProcess = new DevProcess();
            devProcess.setName(releaseStage.getName());
            devProcess.setOrder(Integer.valueOf(releaseStage.getOrder()));
            devProcess.setReleaseId(releaseStage.getSn());

            ReleaseWorkFlows.PipelineConfigVo pipelineConfigVo = releaseStage.getPipeline().getPipeline().getPipelineConfigVo();
            // 调用云效接口获取流水线详情
            String         pipelineDetailRes   = ForestApi.pipelineDetail(pipelineConfigVo.getPipelineId());
            JsonObject     pipelineDetailResJO = GsonUtil.parseStringToJsonObject(pipelineDetailRes);
            PipelineDetail pipelineDetail      = GsonUtil.getGson().fromJson(pipelineDetailResJO, PipelineDetail.class);
            // 将云效接口的流水线响应结构转换为项目中的结构体
            Pipeline pipeline = new Pipeline();
            pipeline.setSn(releaseStage.getSn());
            pipeline.setReleaseWorkflowSn(releaseStage.getReleaseWorkflowSn());
            pipeline.setPipelineId(pipelineConfigVo.getPipelineId());
            List<CodeSource> codeSourceList = getCodeSource(pipelineDetail.getPipelineConfig().getSources());
            pipeline.setCodeSourceList(codeSourceList);
            // 将各阶段的 yaml 格式文本解析为项目中的阶段结构体
            List<PipelineStage> pipelineStageList = getPipelineStage(pipelineConfigVo.getFlow());
            pipeline.setPipelineStageList(pipelineStageList);
            devProcess.setPipeline(pipeline);
            devProcessList.add(devProcess);
        }
        return devProcessList;
    }

    /**
     * @param sources
     * @return java.util.List<com.clic.yunxiao_api.struct.CodeSource>
     * @author synhard
     * @id 18101119
     * @description 获取研发流程的代码源
     * @date 2024/5/29 18:47
     */
    private static List<CodeSource> getCodeSource(List<PipelineDetail.PipelineDetailCodeSource> sources) {
        List<CodeSource> codeSourceList = new ArrayList<>(5);
        for (PipelineDetail.PipelineDetailCodeSource pipelineDetailCodeSource : sources) {
            CodeSource codeSource = new CodeSource();
            codeSource.setBranch(pipelineDetailCodeSource.getData().getBranch());
            codeSource.setEndpoint(pipelineDetailCodeSource.getData().getRepo());
            codeSource.setType(pipelineDetailCodeSource.getType());
            codeSource.setName(pipelineDetailCodeSource.getName());
            codeSourceList.add(codeSource);
        }
        return codeSourceList;
    }

    /**
     * @param flow
     * @return java.util.List<com.clic.yunxiao_api.struct.PipelineStage>
     * @author synhard
     * @id 18101119
     * @description 提取流水线的各个阶段
     * @date 2024/5/29 18:47
     */
    private static List<PipelineStage> getPipelineStage(String flow) {
        List<PipelineStage>  pipelineStageList    = new ArrayList<>(5);
        Yaml                 yaml                 = new Yaml();
        Object               document             = yaml.load(new StringReader(flow));
        PipelineConfigVoFlow pipelineConfigVoFlow = null;
        if (document instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) document;
            if (map.containsKey("stages")) {
                pipelineConfigVoFlow = extractStagesYaml(map.get("stages"));
                // 使用或保存 summary 对象
            } else if (map.containsKey("pipeline")) {
                List<Map<String, Object>> stageList = (List<Map<String, Object>>) map.get("pipeline");
                pipelineConfigVoFlow = extractStagesNonYaml(stageList);
            }
        }
        if (pipelineConfigVoFlow != null) {
            for (PipelineConfigVoFlow.PipelineConfigVoFlowStage pipelineConfigVoFlowStage : pipelineConfigVoFlow.getStages()) {
                PipelineStage          pipelineStage        = new PipelineStage();
                List<PipelineStageJob> pipelineStageJobList = new ArrayList<>(5);
                for (PipelineConfigVoFlow.PipelineConfigVoFlowStageJob pipelineConfigVoFlowStageJob : pipelineConfigVoFlowStage.getJobs()) {
                    PipelineStageJob pipelineStageJob = new PipelineStageJob();
                    pipelineStageJob.setName(pipelineConfigVoFlowStageJob.getName());
                    pipelineStageJobList.add(pipelineStageJob);
                }
                pipelineStage.setPipelineStageJobList(pipelineStageJobList);
                pipelineStage.setName(pipelineConfigVoFlowStage.getName());
                pipelineStageList.add(pipelineStage);
            }
        }
        return pipelineStageList;
    }

    /**
     * @param stagesObj
     * @return com.clic.yunxiao_api.forest.PipelineConfigVoFlow
     * @author synhard
     * @id 18101119
     * @description 提取type=yaml格式的研发流程阶段
     * @date 2024/5/29 18:48
     */
    private static PipelineConfigVoFlow extractStagesYaml(Object stagesObj) {
        Map<String, Object>                                  stages                        = (Map<String, Object>) stagesObj;
        PipelineConfigVoFlow                                 pipelineConfigVoFlow          = new PipelineConfigVoFlow();
        List<PipelineConfigVoFlow.PipelineConfigVoFlowStage> pipelineConfigVoFlowStageList = new ArrayList<>(5);
        for (Map.Entry<String, Object> stageEntry : stages.entrySet()) {
            Map<String, Object>                                     stageValue                       = (Map<String, Object>) stageEntry.getValue();
            String                                                  stageName                        = (String) stageValue.get("name");
            PipelineConfigVoFlow.PipelineConfigVoFlowStage          pipelineConfigVoFlowStage        = new PipelineConfigVoFlow.PipelineConfigVoFlowStage();
            List<PipelineConfigVoFlow.PipelineConfigVoFlowStageJob> pipelineConfigVoFlowStageJobList = new ArrayList<>(5);
            if (stageValue.containsKey("jobs")) {
                Map<String, Object> jobs = (Map<String, Object>) stageValue.get("jobs");
                for (Map.Entry<String, Object> job : jobs.entrySet()) {
                    Map<String, Object>                               jobValue                     = (Map<String, Object>) job.getValue();
                    PipelineConfigVoFlow.PipelineConfigVoFlowStageJob pipelineConfigVoFlowStageJob = new PipelineConfigVoFlow.PipelineConfigVoFlowStageJob();
                    pipelineConfigVoFlowStageJob.setName((String) jobValue.get("name"));
                    pipelineConfigVoFlowStageJobList.add(pipelineConfigVoFlowStageJob);
                }
            }

            pipelineConfigVoFlowStage.setJobs(pipelineConfigVoFlowStageJobList);
            pipelineConfigVoFlowStage.setName(stageName);
            pipelineConfigVoFlowStageList.add(pipelineConfigVoFlowStage);
        }
        pipelineConfigVoFlow.setStages(pipelineConfigVoFlowStageList);
        return pipelineConfigVoFlow;
    }

    /**
     * @param stagesObj
     * @return com.clic.yunxiao_api.forest.PipelineConfigVoFlow
     * @author synhard
     * @id 18101119
     * @description 提取没有type=yaml格式标识的yaml
     * @date 2024/5/29 18:48
     */
    private static PipelineConfigVoFlow extractStagesNonYaml(List<Map<String, Object>> stagesObj) {
        PipelineConfigVoFlow                                 pipelineConfigVoFlow          = new PipelineConfigVoFlow();
        List<PipelineConfigVoFlow.PipelineConfigVoFlowStage> pipelineConfigVoFlowStageList = new ArrayList<>(5);
        for (Map<String, Object> stageObj : stagesObj) {
            PipelineConfigVoFlow.PipelineConfigVoFlowStage          pipelineConfigVoFlowStage        = new PipelineConfigVoFlow.PipelineConfigVoFlowStage();
            List<PipelineConfigVoFlow.PipelineConfigVoFlowStageJob> pipelineConfigVoFlowStageJobList = new ArrayList<>(5);
            List<Object>                                            jobs                             = (List<Object>) stageObj.get("stages");
            String                                                  name                             = (String) stageObj.get("name");
            for (Object job : jobs) {
                List<Map<String, Object>>                         jobInner                     = (List<Map<String, Object>>) ((Map<String, Object>) job).get("jobs");
                PipelineConfigVoFlow.PipelineConfigVoFlowStageJob pipelineConfigVoFlowStageJob = new PipelineConfigVoFlow.PipelineConfigVoFlowStageJob();
                pipelineConfigVoFlowStageJob.setName((String) jobInner.get(0).get("displayName"));
                pipelineConfigVoFlowStageJobList.add(pipelineConfigVoFlowStageJob);
            }
            pipelineConfigVoFlowStage.setJobs(pipelineConfigVoFlowStageJobList);
            pipelineConfigVoFlowStage.setName(name);
            pipelineConfigVoFlowStageList.add(pipelineConfigVoFlowStage);
        }
        pipelineConfigVoFlow.setStages(pipelineConfigVoFlowStageList);
        return pipelineConfigVoFlow;
    }

    /**
     * @param pipelineId    流水线id
     * @param pipelineRunId 流水线运行id
     * @return com.xiaobawang.xjsyy_idea_plugin.forest.RunningDetail
     * @author synhard
     * @description 调用云效，获取运行流水线实例
     * @date 2024/6/5 16:56
     */
    public static RunningDetail runningDetail(Long pipelineId,
                                              Long pipelineRunId) {
        // 调用云效获取运行详情
        String        runningDetailRes = ForestApi.runningDetail(pipelineId, pipelineRunId);
        RunningDetail runningDetail    = GsonUtil.getGson().fromJson(runningDetailRes, RunningDetail.class);
        return runningDetail;
    }

    /**
     * @param releaseWorkflowSn 流水线 sn
     * @param releaseStageSn    流水线阶段 sn
     * @author synhard
     * @id 18101119
     * @description 执行研发阶段流水线
     * @date 2024/6/4 15:52
     */
    public static RunPipelineRes runPipeline(String releaseStageSn, String releaseWorkflowSn) {
        JsonObject body   = new JsonObject();
        JsonObject params = new JsonObject();
        // 运行备注
        params.addProperty("FLOW_INST_RUNNING_COMMENT", "yunxingbeizhu");
        // source_id -> 分支名称
        params.addProperty("ipbps_serviceapp", "master");
        // 参数
        params.addProperty("env", "dev");
        body.add("params", params);
        String         runPipelineRes   = ForestApi.runPipeline(releaseWorkflowSn, releaseStageSn, body.toString());
        RunPipelineRes runningDetailRes = GsonUtil.getGson().fromJson(runPipelineRes, RunPipelineRes.class);
        return runningDetailRes;
    }
}
